Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit 163c6b021fceeec025576f5000c6e3c7a0e248d7


Parents : 417f39d
Author : Mark Qvist <mark@adepta.io>
Date : 2020-05-28T22:18:19+02:00

Reworked queue and buffering

Changes

4 files changed, 288 insertions(+), 132 deletions(-)

M Config.h +13 -34
M Framing.h -3
M RNode_Firmware.ino +116 -95
M Utilities.h +159

Diff

diff --git a/Config.h b/Config.h
index 3d76536..144d78b 100644
--- a/Config.h
+++ b/Config.h
@@ -4,18 +4,14 @@
#define CONFIG_H
#define MAJ_VERS 0x01
- #define MIN_VERS 0x0D
+ #define MIN_VERS 0x0E
- #define MCU_328P 0x90
#define MCU_1284P 0x91
#define MODE_HOST 0x11
#define MODE_TNC 0x12
- #if defined(__AVR_ATmega328P__)
- #define MCU_VARIANT MCU_328P
- #warning "Firmware is being compiled for atmega328p based boards"
- #elif defined(__AVR_ATmega1284P__)
+ #if defined(__AVR_ATmega1284P__)
#define MCU_VARIANT MCU_1284P
#warning "Firmware is being compiled for atmega1284p based boards"
#else
@@ -25,22 +21,11 @@
#define MTU 500
#define SINGLE_MTU 255
#define HEADER_L 1
+ #define MIN_L 1
+
#define CMD_L 4
// MCU dependent configuration parameters
- #if MCU_VARIANT == MCU_328P
- const int pin_cs = 7;
- const int pin_reset = 6;
- const int pin_dio = 2;
- const int pin_led_rx = 5;
- const int pin_led_tx = 4;
-
- #define FLOW_CONTROL_ENABLED true
- #define QUEUE_SIZE 0
-
- #define EEPROM_SIZE 512
- #define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
- #endif
#if MCU_VARIANT == MCU_1284P
const int pin_cs = 4;
@@ -49,10 +34,9 @@
const int pin_led_rx = 12;
const int pin_led_tx = 13;
- #define FLOW_CONTROL_ENABLED true
- #define QUEUE_SIZE 24
- #define QUEUE_BUF_SIZE (QUEUE_SIZE+1)
- #define QUEUE_MEM QUEUE_BUF_SIZE * MTU
+ #define CONFIG_UART_BUFFER_SIZE 6750
+ #define CONFIG_QUEUE_SIZE 6750
+ #define CONFIG_QUEUE_MAX_LENGTH 70
#define EEPROM_SIZE 4096
#define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
@@ -67,7 +51,6 @@
// SX1276 RSSI offset to get dBm value from
// packet RSSI register
const int rssi_offset = 157;
- const int snr_offset = 128;
// Default LoRa settings
int lora_sf = 0;
@@ -91,23 +74,19 @@
uint8_t last_snr_raw = 0x00;
size_t read_len = 0;
uint8_t seq = 0xFF;
+
+ // Incoming packet buffer
uint8_t pbuf[MTU];
- uint8_t sbuf[MTU];
+
+ // KISS command buffer
uint8_t cbuf[CMD_L];
- #if QUEUE_SIZE > 0
- uint8_t tbuf[MTU];
- uint8_t qbuf[QUEUE_MEM];
- size_t queued_lengths[QUEUE_BUF_SIZE];
- #endif
+ // LoRa transmit buffer
+ uint8_t tbuf[MTU];
uint32_t stat_rx = 0;
uint32_t stat_tx = 0;
- bool outbound_ready = false;
- size_t queue_head = 0;
- size_t queue_tail = 0;
-
bool stat_signal_detected = false;
bool stat_signal_synced = false;
bool stat_rx_ongoing = false;

diff --git a/Framing.h b/Framing.h
index 10b380c..80ec1cd 100644
--- a/Framing.h
+++ b/Framing.h
@@ -55,9 +55,6 @@
size_t frame_len;
bool IN_FRAME = false;
bool ESCAPE = false;
- bool SERIAL_READING = false;
uint8_t command = CMD_UNKNOWN;
- uint32_t last_serial_read = 0;
- uint32_t serial_read_timeout_ms = 60;
#endif
\ No newline at end of file

diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino
index b961f11..4eeb49b 100644
--- a/RNode_Firmware.ino
+++ b/RNode_Firmware.ino
@@ -2,27 +2,49 @@
#include <SPI.h>
#include "Utilities.h"
+FIFOBuffer serialFIFO;
+uint8_t serialBuffer[CONFIG_UART_BUFFER_SIZE];
+
+FIFOBuffer16 packet_starts;
+size_t packet_starts_buf[CONFIG_QUEUE_MAX_LENGTH+1];
+
+FIFOBuffer16 packet_lengths;
+size_t packet_lengths_buf[CONFIG_QUEUE_MAX_LENGTH+1];
+
+uint8_t packet_queue[CONFIG_QUEUE_SIZE];
+
+volatile uint8_t queue_height = 0;
+volatile size_t queued_bytes = 0;
+volatile size_t queue_cursor = 0;
+volatile size_t current_packet_start = 0;
+
void setup() {
// Seed the PRNG
randomSeed(analogRead(0));
// Initialise serial communication
+ memset(serialBuffer, 0, sizeof(serialBuffer));
+ fifo_init(&serialFIFO, serialBuffer, sizeof(serialBuffer));
+
Serial.begin(serial_baudrate);
while (!Serial);
+ serial_timer_init();
+
// Configure input and output pins
pinMode(pin_led_rx, OUTPUT);
pinMode(pin_led_tx, OUTPUT);
// Initialise buffers
memset(pbuf, 0, sizeof(pbuf));
- memset(sbuf, 0, sizeof(sbuf));
memset(cbuf, 0, sizeof(cbuf));
- #if QUEUE_SIZE > 0
- memset(qbuf, 0, sizeof(qbuf));
- memset(queued_lengths, 0, sizeof(queued_lengths));
- #endif
+ memset(packet_queue, 0, sizeof(packet_queue));
+ memset(packet_starts_buf, 0, sizeof(packet_starts));
+ memset(packet_lengths_buf, 0, sizeof(packet_lengths));
+
+ fifo16_init(&packet_starts, packet_starts_buf, sizeof(packet_starts_buf));
+ fifo16_init(&packet_lengths, packet_lengths_buf, sizeof(packet_lengths_buf));
// Set chip select, reset and interrupt
// pins for the LoRa module
@@ -188,66 +210,37 @@ void receiveCallback(int packet_size) {
}
}
-
-bool outboundReady() {
- #if QUEUE_SIZE > 0
- if (queue_head != queue_tail) {
- return true;
- } else {
- return false;
- }
- #else
- return outbound_ready;
- #endif
-}
-
bool queueFull() {
- size_t new_queue_head = (queue_head+1)%QUEUE_BUF_SIZE;
- if (new_queue_head == queue_tail) {
- return true;
- } else {
- return false;
- }
+ return (queue_height < CONFIG_QUEUE_MAX_LENGTH && queued_bytes < CONFIG_QUEUE_SIZE);
}
-void enqueuePacket(size_t length) {
- size_t new_queue_head = (queue_head+1)%QUEUE_BUF_SIZE;
- if (new_queue_head != queue_tail) {
- queued_lengths[queue_head] = length;
- size_t insert_addr = queue_head * MTU;
- for (int i = 0; i < length; i++) {
- qbuf[insert_addr+i] = sbuf[i];
- }
- queue_head = new_queue_head;
- if (!queueFull()) {
- kiss_indicate_ready();
- }
- } else {
- kiss_indicate_error(ERROR_QUEUE_FULL);
- }
-}
-
-#if QUEUE_SIZE > 0
-void processQueue() {
- size_t fetch_address = queue_tail*MTU;
- size_t fetch_length = queued_lengths[queue_tail];
-
- for (int i = 0; i < fetch_length; i++) {
- tbuf[i] = qbuf[fetch_address+i];
- qbuf[fetch_address+i] = 0x00;
- }
-
- queued_lengths[queue_tail] = 0;
+volatile bool queue_flushing = false;
+void flushQueue(void) {
+ if (!queue_flushing) {
+ queue_flushing = true;
- queue_tail = ++queue_tail%QUEUE_BUF_SIZE;
+ size_t processed = 0;
+ for (size_t n = 0; n < queue_height; n++) {
+ size_t start = fifo16_pop_locked(&packet_starts);
+ size_t length = fifo16_pop_locked(&packet_lengths);
- transmit(fetch_length);
+ if (length >= MIN_L) {
+ for (size_t i = 0; i < length; i++) {
+ size_t pos = (start+i)%CONFIG_QUEUE_SIZE;
+ tbuf[i] = packet_queue[pos];
+ }
- if (!queueFull()) {
- kiss_indicate_ready();
+ transmit(length);
+ processed++;
+ }
+ }
}
+
+ queue_height = 0;
+ queued_bytes = 0;
+ queue_flushing = false;
+ kiss_indicate_ready();
}
-#endif
void transmit(size_t size) {
if (radio_online) {
@@ -264,11 +257,7 @@ void transmit(size_t size) {
LoRa.write(header); written++;
for (size_t i; i < size; i++) {
- #if QUEUE_SIZE > 0
- LoRa.write(tbuf[i]);
- #else
- LoRa.write(sbuf[i]);
- #endif
+ LoRa.write(tbuf[i]);
written++;
@@ -298,11 +287,7 @@ void transmit(size_t size) {
LoRa.beginPacket();
for (size_t i; i < size; i++) {
- #if QUEUE_SIZE > 0
- LoRa.write(tbuf[i]);
- #else
- LoRa.write(sbuf[i]);
- #endif
+ LoRa.write(tbuf[i]);
written++;
}
@@ -315,26 +300,35 @@ void transmit(size_t size) {
kiss_indicate_error(ERROR_TXFAILED);
led_indicate_error(5);
}
-
- #if QUEUE_SIZE == 0
- if (FLOW_CONTROL_ENABLED)
- kiss_indicate_ready();
- #endif
}
void serialCallback(uint8_t sbyte) {
if (IN_FRAME && sbyte == FEND && command == CMD_DATA) {
IN_FRAME = false;
- if (QUEUE_SIZE == 0) {
- if (outbound_ready) {
- kiss_indicate_error(ERROR_QUEUE_FULL);
- } else {
- outbound_ready = true;
- }
- } else {
- enqueuePacket(frame_len);
+ if (queue_height < CONFIG_QUEUE_MAX_LENGTH && queued_bytes < CONFIG_QUEUE_SIZE) {
+ size_t s = current_packet_start;
+ size_t e = queue_cursor-1; if (e == -1) e = CONFIG_QUEUE_SIZE-1;
+ size_t l;
+
+ if (s != e) {
+ l = (s < e) ? e - s + 1 : CONFIG_QUEUE_SIZE - s + e + 1;
+ } else {
+ l = 1;
+ }
+
+ if (l >= MIN_L) {
+ queue_height++;
+
+ fifo16_push_locked(&packet_starts, s);
+ fifo16_push_locked(&packet_lengths, l);
+
+ current_packet_start = queue_cursor;
+ }
}
+
+ if (!queueFull()) kiss_indicate_ready();
+
} else if (sbyte == FEND) {
IN_FRAME = true;
command = CMD_UNKNOWN;
@@ -352,7 +346,11 @@ void serialCallback(uint8_t sbyte) {
if (sbyte == TFESC) sbyte = FESC;
ESCAPE = false;
}
- sbuf[frame_len++] = sbyte;
+ if (queue_height < CONFIG_QUEUE_MAX_LENGTH && queued_bytes < CONFIG_QUEUE_SIZE) {
+ queued_bytes++;
+ packet_queue[queue_cursor++] = sbyte;
+ if (queue_cursor == CONFIG_QUEUE_SIZE) queue_cursor = 0;
+ }
}
} else if (command == CMD_FREQUENCY) {
if (sbyte == FESC) {
@@ -566,19 +564,20 @@ void validateStatus() {
void loop() {
if (radio_online) {
checkModemStatus();
- if (outboundReady() && !SERIAL_READING) {
+
+ if (queue_height > 0) {
if (!dcd_waiting) updateModemStatus();
+
if (!dcd && !dcd_led) {
if (dcd_waiting) delay(lora_rx_turnaround_ms);
+
updateModemStatus();
+
if (!dcd) {
dcd_waiting = false;
- #if QUEUE_SIZE > 0
- processQueue();
- #else
- outbound_ready = false;
- transmit(frame_len);
- #endif
+
+ flushQueue();
+
}
} else {
dcd_waiting = true;
@@ -594,14 +593,36 @@ void loop() {
}
}
- if (Serial.available()) {
- SERIAL_READING = true;
- char sbyte = Serial.read();
+ serial_poll();
+}
+
+void serial_poll() {
+ while (!fifo_isempty_locked(&serialFIFO)) {
+ char sbyte = fifo_pop_locked(&serialFIFO);
serialCallback(sbyte);
- last_serial_read = millis();
- } else {
- if (SERIAL_READING && millis()-last_serial_read >= serial_read_timeout_ms) {
- SERIAL_READING = false;
+ }
+}
+
+void buffer_serial() {
+ while (Serial.available()) {
+ char c = Serial.read();
+ if (!fifo_isfull_locked(&serialFIFO)) {
+ fifo_push_locked(&serialFIFO, c);
}
}
}
+
+void serial_timer_init() {
+ TCCR3A = 0;
+ TCCR3B = _BV(CS10) |
+ _BV(WGM33)|
+ _BV(WGM32);
+
+ ICR3 = 23704; // Approximation of 16Mhz / 675
+
+ TIMSK3 = _BV(ICIE3);
+}
+
+ISR(TIMER3_CAPT_vect) {
+ buffer_serial();
+}
\ No newline at end of file

diff --git a/Utilities.h b/Utilities.h
index 2753fad..9aae3f6 100644
--- a/Utilities.h
+++ b/Utilities.h
@@ -1,4 +1,6 @@
#include <EEPROM.h>
+#include <stddef.h>
+#include <util/atomic.h>
#include "LoRa.h"
#include "ROM.h"
#include "Config.h"
@@ -468,3 +470,160 @@ void unlock_rom() {
led_indicate_error(50);
eeprom_erase();
}
+
+typedef struct FIFOBuffer
+{
+ unsigned char *begin;
+ unsigned char *end;
+ unsigned char * volatile head;
+ unsigned char * volatile tail;
+} FIFOBuffer;
+
+inline bool fifo_isempty(const FIFOBuffer *f) {
+ return f->head == f->tail;
+}
+
+inline bool fifo_isfull(const FIFOBuffer *f) {
+ return ((f->head == f->begin) && (f->tail == f->end)) || (f->tail == f->head - 1);
+}
+
+inline void fifo_push(FIFOBuffer *f, unsigned char c) {
+ *(f->tail) = c;
+
+ if (f->tail == f->end) {
+ f->tail = f->begin;
+ } else {
+ f->tail++;
+ }
+}
+
+inline unsigned char fifo_pop(FIFOBuffer *f) {
+ if(f->head == f->end) {
+ f->head = f->begin;
+ return *(f->end);
+ } else {
+ return *(f->head++);
+ }
+}
+
+inline void fifo_flush(FIFOBuffer *f) {
+ f->head = f->tail;
+}
+
+static inline bool fifo_isempty_locked(const FIFOBuffer *f) {
+ bool result;
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ result = fifo_isempty(f);
+ }
+ return result;
+}
+
+static inline bool fifo_isfull_locked(const FIFOBuffer *f) {
+ bool result;
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ result = fifo_isfull(f);
+ }
+ return result;
+}
+
+static inline void fifo_push_locked(FIFOBuffer *f, unsigned char c) {
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ fifo_push(f, c);
+ }
+}
+
+static inline unsigned char fifo_pop_locked(FIFOBuffer *f) {
+ unsigned char c;
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ c = fifo_pop(f);
+ }
+ return c;
+}
+
+inline void fifo_init(FIFOBuffer *f, unsigned char *buffer, size_t size) {
+ f->head = f->tail = f->begin = buffer;
+ f->end = buffer + size -1;
+}
+
+inline size_t fifo_len(FIFOBuffer *f) {
+ return f->end - f->begin;
+}
+
+typedef struct FIFOBuffer16
+{
+ size_t *begin;
+ size_t *end;
+ size_t * volatile head;
+ size_t * volatile tail;
+} FIFOBuffer16;
+
+inline bool fifo16_isempty(const FIFOBuffer16 *f) {
+ return f->head == f->tail;
+}
+
+inline bool fifo16_isfull(const FIFOBuffer16 *f) {
+ return ((f->head == f->begin) && (f->tail == f->end)) || (f->tail == f->head - 1);
+}
+
+inline void fifo16_push(FIFOBuffer16 *f, size_t c) {
+ *(f->tail) = c;
+
+ if (f->tail == f->end) {
+ f->tail = f->begin;
+ } else {
+ f->tail++;
+ }
+}
+
+inline size_t fifo16_pop(FIFOBuffer16 *f) {
+ if(f->head == f->end) {
+ f->head = f->begin;
+ return *(f->end);
+ } else {
+ return *(f->head++);
+ }
+}
+
+inline void fifo16_flush(FIFOBuffer16 *f) {
+ f->head = f->tail;
+}
+
+static inline bool fifo16_isempty_locked(const FIFOBuffer16 *f) {
+ bool result;
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ result = fifo16_isempty(f);
+ }
+ return result;
+}
+
+static inline bool fifo16_isfull_locked(const FIFOBuffer16 *f) {
+ bool result;
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ result = fifo16_isfull(f);
+ }
+ return result;
+}
+
+static inline void fifo16_push_locked(FIFOBuffer16 *f, size_t c) {
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ fifo16_push(f, c);
+ }
+}
+
+static inline size_t fifo16_pop_locked(FIFOBuffer16 *f) {
+ size_t c;
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ c = fifo16_pop(f);
+ }
+ return c;
+}
+
+inline void fifo16_init(FIFOBuffer16 *f, size_t *buffer, size_t size) {
+ f->head = f->tail = f->begin = buffer;
+ f->end = buffer + (size/sizeof(size_t)) - 2;
+}
+
+inline size_t fifo16_len(FIFOBuffer16 *f) {
+ return ((f->end - f->begin))/sizeof(size_t);
+}
+


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────